package org.hxzon.rpggame.test;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class NettyClientMain2 {
    private static final Logger logger = LoggerFactory.getLogger(NettyClientMain2.class);
    //
    private static final String host = "localhost";

    public static void main(String[] args) {
        new NettyClient(host, Util.serverPort);
    }

    public static class NettyClient {

        public NettyClient(String host, int serverPort) {
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            try {
                Bootstrap b = new Bootstrap(); // (1)
                b.group(workerGroup); // (2)
                b.channel(NioSocketChannel.class); // (3)
                b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
                b.handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Util.MaxFrameLength, 0, Util.LengthFieldLength));
                        ch.pipeline().addLast(new LengthFieldPrepender(Util.LengthFieldLength));
                        ch.pipeline().addLast(new ClientHandler());
                    }
                });

                // Start the client.
                Channel channel = b.connect(host, serverPort).sync().channel(); // (5)
                // Read commands from the stdin.
                ChannelFuture lastWriteFuture = null;
                BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
                for (;;) {
                    String str = in.readLine();
                    if (str == null) {
                        break;
                    }

                    // Sends the received line to the server.
                    ByteBuf wBuf = channel.alloc().buffer();
                    Util.writeCmd(wBuf, 1);
                    Util.writeString(wBuf, str);
                    lastWriteFuture = channel.writeAndFlush(wBuf);

                    // If user typed the 'bye' command, wait until the server closes
                    // the connection.
                    if ("bye".equals(str.toLowerCase())) {
                        channel.closeFuture().sync();
                        break;
                    }
                }

                // Wait until all messages are flushed before closing the channel.
                if (lastWriteFuture != null) {
                    lastWriteFuture.sync();
                }
            } catch (Exception e) {
                logger.error("", e);
            } finally {
                workerGroup.shutdownGracefully();
            }
        }

    }

}
